home *** CD-ROM | disk | FTP | other *** search
- /*------------------------------------------------------------------------------
- #
- # Apple Developer Technical Support
- #
- # SmallDaemon
- # A small faceless background-only application
- #
- # main.c - C Source
- #
- # Copyright © 1991-1995 Apple Computer, Inc.
- # All rights reserved.
- #
- # Versions:
- # 1.0.2 06/95 Jim Luther Added IncreaseApplicationStack from the
- # Tech Note "PS 2 - Background-Only Applications".
- # 1.0.1 02/95 Jim Luther Cleaned up source and made it compatible
- # with the Universal Interfaces.
- # 1.0 09/91 C.K. Haun <TR>
- #
- # Components:
- # main.c
- # AppleEvents.c
- #
- # This is a _very_ simple sample showing a do-nothing
- # System 7.0 faceless background application.
- #
- # The main things to note are…
- # 1) Look at the SIZE resource for the flag settings you'll
- # need to let the Finder™ know that you only want to work
- # in the background.
- # 2) Notice that you really do have your own heap and your own
- # event loop. You can do anything a foreground application
- # can do, send AppleEvents, PPC stuff, anything else you'd
- # like EXCEPT a graphic interface.
- # 3) NOTE that no managers are started up. You cannot start up
- # Window, Menu, Dialogs, or anything else that
- # deals with the graphic front end. Just leave them out.
- # You _should_ start up QuickDraw, to use some
- # QuickDraw functions (like offscreen ports) and because
- # other parts of the Macintosh Toolbox (parts which you may
- # not suspect) depend on having QuickDraw initialized,
- # but you CANNOT actually do any screen drawing.
- #
- # Of course, a backgrounder can be launched from the Finder™
- # with a double-click. However, if you'd like the backgrounder
- # to perform some useful service for your main application, driver,
- # DA, or whatever, you will want it running all the time.
- # The BEST way to insure this is to install the backgrounder in the
- # StartUp Items folder in the system folder. This will insure that
- # it is always launched, and it will also reduce memory fragmentation
- # since it will be installed at startup time. You can search for it
- # when you need it with IPCListPorts (see the PPC toolbox documentation).
- # Optionally, you can use the LaunchApplication trap to launch it
- # when you need it, and kill it when you're done. But this could
- # cause some multiFinder heap fragmentation.
- #
- # And remember, it's a backgrounder, you can't see it. To kill it
- # use TaskIt or ProcDoggie.
- #
- # ---------------------------------------------------------------
- # Use this sample as a starting point, and adapt its' routines to
- # meet the specific needs of your project.
- #
- ------------------------------------------------------------------------------*/
-
- /*
- ** This doesn't do much but wait for a quit event. But, you can expand it
- ** to suit whatever your needs are for a backgrounder.
- ** Be sure to look at the SIZE resource for this app to see how the
- ** flags should be set for a background-only task.
- */
-
- #include <Types.h>
- #include <MixedMode.h>
- #include <Memory.h>
- #include <Errors.h>
- #include <OSUtils.h>
- #include <QuickdrawText.h>
- #include <QuickDraw.h>
- #include <Events.h>
- #include <AppleTalk.h>
- #include <Files.h>
- #include <PPCToolbox.h>
- #include <Processes.h>
- #include <EPPC.h>
- #include <Notification.h>
- #include <AppleEvents.h>
- #include <Gestalt.h>
- #include <SegLoad.h>
-
- /*
- ** Constants
- */
-
- enum
- {
- /*
- ** A long time, long time. Change this if you'd like to do
- ** null processing or if you're depending on WakeUpProcess called from
- ** a completion routine to start non-interrupt processingh. Just keep
- ** in mind that the user does NOT know that you exist, and if you are
- ** eating up a bunch of time, the user will not know why the system
- ** is slowing down.
- */
- kSleepTime = 50000
- };
-
- /*
- ** Types
- */
-
- /* A little struct to install AE handlers from. Makes it easier to plug in */
- /* new handlers. */
- struct AEinstalls
- {
- AEEventClass theClass;
- AEEventID theEvent;
- ProcPtr theProc;
- };
- typedef struct AEinstalls AEinstalls;
-
- /*
- ** Global variables
- */
-
- Boolean gQuit = false;
- EventRecord gERecord;
- Boolean gHasAppleEvents;
- unsigned long gMySleep = kSleepTime;
-
-
- /*
- ** Function prototypes
- */
-
- OSErr IncreaseApplicationStack(Size incrementSize);
- pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
- pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
- pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
- pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn);
- void DoHighLevel(EventRecord *AERecord);
- void InitAEStuff(void);
-
- void main(void)
- {
- /*
- ** If your FBA needs extra stack space, call IncreaseApplicationStack here
- ** to increase the stack space. Remember to increase your heap size by the
- ** the same amount.
- */
- // IncreaseApplicationStack(22*1024); /* Get another 22K of stack space */
-
- /*
- ** We are NOT initializing any managers except for QuickDraw. We're in
- ** the background, with no user interface, we can't use windows or dialogs
- ** or menus. If you need to talk to the user you can post a notification,
- ** or launch an application to communicate. Passing an AppleEvent in the
- ** launchapplication trap could do the communication for you.
- */
-
- InitGraf(&qd.thePort);
-
- /* Routine to install Apple event handlers */
- InitAEStuff();
-
- /* no nothing but high level events */
- while ( gQuit == false )
- {
- (void) WaitNextEvent(highLevelEventMask, &gERecord, gMySleep, 0);
- switch ( gERecord.what )
- {
- case nullEvent:
- /* no null processing in this example */
- break;
-
- case kHighLevelEvent:
- DoHighLevel(&gERecord);
- break;
-
- default:
- break;
- }
- }
- }
-
- /*
- ** Increase the space allocated for the application stack.
- **
- ** Warning: SetApplLimit always sets the stack to at least as large as the
- ** default stack for the machine (8K on machines with original QuickDraw,
- ** 24K on machines with Color QuickDraw), so the application partition
- ** must be large enough to accommodate an appropriate stack and heap.
- **
- ** Call this only once, at the beginning of the application.
- **
- ** Another warning:
- ** Don't bother trying to set the stack size to something lower than 24K.
- ** If SetApplLimit is called to do this, it will silently lower ApplLimit
- ** to a 24K stack.
- */
- OSErr IncreaseApplicationStack(Size incrementSize)
- {
- OSErr result;
-
- /* Increase the stack size by lowering the heap limit. */
- SetApplLimit((Ptr) ((unsigned long) GetApplLimit() - incrementSize));
- result = MemError();
- if ( result == noErr )
- MaxApplZone();
-
- return ( result );
- }
-
- /*
- ** Here are the AppleEvent handlers for this background-only task.
- ** Since this is a real live application, it can accept and send any
- ** Apple Events you want to send or receive.
- ** In this case, the only ones that make any sense in this app are
- ** 'oapp' and 'quit'
- */
-
- /*
- ** InitAEStuff checks for the availability of the AppleEvent Manager and
- ** installs our event handlers.
- ** If the AppleEvent Manager isn't around, we bail.
- */
- void InitAEStuff(void)
- {
- static AEinstalls HandlersToInstall[] =
- {
- {
- kCoreEventClass, kAEOpenApplication, (ProcPtr)AEOpenHandler
- },
- {
- kCoreEventClass, kAEOpenDocuments, (ProcPtr)AEOpenDocHandler
- },
- {
- kCoreEventClass, kAEQuitApplication, (ProcPtr)AEQuitHandler
- },
- {
- kCoreEventClass, kAEPrintDocuments, (ProcPtr)AEPrintHandler
- },
- /* The above are the four required AppleEvents. */
- };
-
- OSErr aevtErr = noErr;
- long aLong = 0;
- Boolean gHasAppleEvents = false;
-
- /*
- ** Check this machine for AppleEvents. If they are not here (ie not 7.0)
- ** then we exit
- */
- gHasAppleEvents = (Gestalt(gestaltAppleEventsAttr, &aLong) == noErr);
-
- /*
- ** The following series of calls installs all our AppleEvent Handlers.
- ** These handlers are added to the application event handler list that
- ** the AppleEvent manager maintains. So, whenever an AppleEvent happens
- ** and we call AEProcessEvent, the AppleEvent manager will check our
- ** list of handlers and dispatch to it if there is one.
- */
- if ( gHasAppleEvents )
- {
- register qq;
- for ( qq = 0;
- qq < ((sizeof(HandlersToInstall) / sizeof(AEinstalls)));
- qq++)
- {
- aevtErr = AEInstallEventHandler(HandlersToInstall[qq].theClass, HandlersToInstall[qq].theEvent,
- NewAEEventHandlerProc(HandlersToInstall[qq].theProc), 0, false);
- if ( aevtErr != noErr )
- {
- /*
- ** Of course, you can't tell the user why you died directly,
- ** since you have no face. But, you can post a notification
- ** from here to let them know.
- */
- ExitToShell(); /* just fail, baby */
- }
- }
- }
- else
- {
- ExitToShell();
- }
- }
-
-
- void DoHighLevel(EventRecord *AERecord)
- {
- /*
- ** I'm not doing any error handling here because there's not a lot
- ** I can do, just pass the errors back.
- */
- AEProcessAppleEvent(AERecord);
- }
-
-
- /* This is the standard Open Application event. */
- pascal OSErr AEOpenHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused (messagein,reply,refIn)
- /*
- ** We of course don't do anything here, since we're background only
- ** But this was a normal launch, so return noErr
- */
- return ( noErr );
- }
-
-
- /*
- ** Open Doc, opens our documents.
- ** In this case, of course, you are in the background so you should return
- ** an error here since you're not opening a document.
- ** Of course, you _might_ want to open a doc, but you will probably
- ** confuse the user if you do, since they will see no action as the
- ** result of their clicking on a document icon.
- */
- pascal OSErr AEOpenDocHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused (reply, refIn,messagein)
- /*
- ** We of course don't do anything here, so tell the sender that we
- ** didn't handle the event
- */
- return ( errAEEventNotHandled );
- }
-
-
- /* Same logic for printing */
- pascal OSErr AEPrintHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused (reply,refIn,messagein)
- /*
- ** We of course don't do anything here, so tell the sender that we
- ** didn't handle the event
- */
- return ( errAEEventNotHandled );
- }
-
-
- /*
- ** Standard Quit event handler, to handle a Quit event from the Finder,
- ** for example.
- ** ••••• DO NOT CALL EXITTOSHELL HERE ••••• or you will never have
- ** a happy life.
- */
- pascal OSErr AEQuitHandler(AppleEvent *messagein, AppleEvent *reply, long refIn)
- {
- #pragma unused (messagein,refIn,reply)
- /*
- ** This does _NOT_ quit, you should NEVER quit from an AppleEvent
- ** handler. Calling ExitToShell here would blow up the Finder™
- */
- gQuit = true;
- return ( noErr );
- }
-